package uml.GUI;

import java.awt.MenuItem;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.Collection;
import java.util.HashMap;

import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;

import uml.eventsystem.IObserver;
import uml.eventsystem.ISubject;
import uml.eventsystem.SubjectImpl;
import uml.eventsystem.events.UMLEventId;
import uml.util.UMLConstants;

public class CommandRibbon
		extends JMenuBar
		implements ActionListener, ISubject
{
	/**
	 * Lookup table
	 */
	private HashMap<String, UMLEventId> eventIDLookupTable;
	private SubjectImpl m_subjImpl;

	/**
	 * Creates a default <tt>CommandRibbon</tt> with all menus already
	 * initialized
	 * 
	 * @param controller
	 */
	public CommandRibbon (IObserver observer)
	{
		m_subjImpl = new SubjectImpl (this);
		eventIDLookupTable = new HashMap<String, UMLEventId> ();
		add (initFileMenu ());
		add (initEdit ());
		add (initObjects ());
		//add (initHelp ());
		registerEvents (observer);
		//System.out.println (m_keyMap.toString ());
	}

	/**
	 * Registsers observer for all events this class uses
	 * 
	 * @param controller
	 */
	private void registerEvents (IObserver observer)
	{
		Collection<UMLEventId> eventIds = eventIDLookupTable.values ();
		for (UMLEventId eventId : eventIds)
			addObserver (observer, eventId);
	}

	@Override
	public void actionPerformed (ActionEvent e)
	{
		String menuName = e.getActionCommand ();
		UMLEventId event = eventIDLookupTable.get (menuName);
		notifyObservers (event);
	}

	/**
	 * Adds a new menu option to the menu with its name name and
	 * <tt>UMLEventId</tt> event
	 * 
	 * @param name
	 * @param event
	 * @param menu
	 */
	private void addMenuItem (String name, KeyStroke stroke, UMLEventId event, JMenuItem menu)
	{
		JMenuItem item = new JMenuItem (name);
		item.setAccelerator (stroke);
		item.addActionListener (this);
		eventIDLookupTable.put (name, event);
		menu.add (item);
	}

	@Override
	public void addObserver (IObserver observer, UMLEventId eventId)
	{
		m_subjImpl.addObserver (observer, eventId);
	}

	@Override
	public void removeObserver (IObserver observer, UMLEventId eventId)
	{
		m_subjImpl.removeObserver (observer, eventId);
	}

	@Override
	public void notifyObservers (UMLEventId eventId)
	{
		m_subjImpl.notifyObservers (eventId);
	}

	/**
	 * Creates all the file menus
	 * 
	 * @return
	 */
	private JMenu initFileMenu ()
	{
		JMenu j = new JMenu ("File");
		j.setMnemonic ('F');
		addMenuItem("New Tab", UMLConstants.NEW_DIAGRAM_STROKE, UMLEventId.CREATE_DIAGRAM, j);
			
		addMenuItem ("Close Tab", UMLConstants.CLOSE_DIAGRAM_STROKE, UMLEventId.CLOSE_DIAGRAM, j);
		addMenuItem ("Save", UMLConstants.SAVE_STROKE, UMLEventId.SAVE, j);
		addMenuItem ("Save As", null, UMLEventId.SAVEAS, j);
		addMenuItem ("Open", UMLConstants.LOAD_STROKE, UMLEventId.OPEN, j);
		addMenuItem ("Print", UMLConstants.PRINT_STROKE, UMLEventId.PRINT, j);
		addMenuItem ("Exit", UMLConstants.EXIT_STROKE, UMLEventId.APPLICATION_EXIT, j);
		return j;
	}

	private JMenu initEdit ()
	{
		JMenu j = new JMenu ("Edit");
		j.setMnemonic ('E');
		//addMenuItem ("Copy", UMLEventId.SYSTEM, j);
		//addMenuItem ("Paste", UMLEventId.SYSTEM, j);
		//addMenuItem ("Select All", UMLEventId.SYSTEM, j);
		addMenuItem ("Delete", UMLConstants.DELETE_STROKE, UMLEventId.DELETE, j);
		return j;
	}

	private JMenu initObjects ()
	{
		JMenu j = new JMenu ("Objects");
		j.setMnemonic ('O');
		j.add (initClassbox ());
		j.add (initRelationship ());
		return j;
	}

	private JMenu initClassbox ()
	{
		JMenu j = new JMenu ("Classbox");
		addMenuItem ("Abstract Class", UMLConstants.ABSTRACT_CLASS_STROKE, UMLEventId.MAKE_ABSTRACT, j);
		addMenuItem ("Simple Class", UMLConstants.SIMPLE_CLASS_STROKE, UMLEventId.MAKE_SIMPLE, j);
		addMenuItem ("Abstract Simple Class", null, UMLEventId.MAKE_SIMPLE_ABSTRACT, j);
		addMenuItem ("Class", UMLConstants.CLASS_STROKE, UMLEventId.MAKE_CLASS, j);
		addMenuItem ("Interface", UMLConstants.INTERFACE_STROKE, UMLEventId.MAKE_INTERFACE, j);
		addMenuItem ("Note", UMLConstants.NOTE_STROKE, UMLEventId.MAKE_NOTE, j);
		addMenuItem ("Package", UMLConstants.PACKAGE_STROKE, UMLEventId.MAKE_PACKAGE, j);
		return j;
	}

	private JMenu initRelationship ()
	{
		JMenu j = new JMenu ("Relationship");
		addMenuItem ("Aggregation", UMLConstants.AGGREGATION_STROKE, UMLEventId.MAKE_AGGREGATION, j);
		addMenuItem ("Association", UMLConstants.ASSOCIATION_STROKE, UMLEventId.MAKE_ASSOCIATION, j);
		addMenuItem ("Composition", UMLConstants.COMPOSITION_STROKE, UMLEventId.MAKE_COMPOSITION, j);
		addMenuItem ("Generalization", UMLConstants.GENERALIZATION_STROKE, UMLEventId.MAKE_GENERALIZATION, j);
		return j;
	}

	private JMenu initHelp ()
	{
		JMenu j = new JMenu ("Help");
		addMenuItem ("Shortcuts", null, UMLEventId.SYSTEM, j);
		addMenuItem ("About", null, UMLEventId.SYSTEM, j);
		return j;
	}
}
